﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using FlexFlow;
using FlexFlow.Model;
using System.IO;
using FlexFlow.Base;
using System.Web;
using System.Threading;
using FlexFlow.Base.File;

namespace FlexFlow.Runtime.BuildService
{
    /// <summary>
    /// 表示表单模板编译器
    /// </summary>
    public class FormTemplateCompiler : ManagerBase
    {
        private WorkFlowFormConventer conventer = new WorkFlowFormConventer();
        private Task compileTask;
        private NotificationCatalogFactory catInfoFactory = new NotificationCatalogFactory()
        {
            Sender = "表单编译器",
            DefaultDescription = "表单处理通知",
            DefaultType = NotificationType.Info
        };

        /// <summary>
        /// 表示用来存放已经编译的表单的文件夹路径
        /// </summary>
        public static string CompiledFormSavePath { get; set; }
        /// <summary>
        /// 获取或设置默认的表单模板编译器
        /// </summary>
        public static FormTemplateCompiler Default { get; set; }

        /// <summary>
        /// 编译大循环
        /// </summary>
        private void CompileAll()
        {
            while (true)
            {
                //从数据库中读取一个没有被编译的模板
                FormTemplate temp = this.Components.FormTemplateProvider.GetAndSetState();
                if (temp == null)
                {
                    Thread.Sleep(1000);
                }
                else
                {
                    //编译
                    CompileOne(temp);
                }

            }
        }
        /// <summary>
        /// 编译一个模板
        /// </summary>
        /// <param name="temp">
        /// 要编译的模板
        /// </param>
        private void CompileOne(FormTemplate temp)
        {
            FileDescription fileDes = null;
            NotificationCatalog catalog = catInfoFactory.CreateCatalog(temp.Installer);
            try
            {
                if (temp == null)
                {
                    return;
                }

                fileDes = this.Components.FileDescriptionProvider.Get(temp.PhysicalFileId);
                if (fileDes == null)
                {
                    //更新文件描述状态，以防止重复安装
                    this.Components.FormTemplateProvider.UpdateState(temp.Identity, FormTemplateState.Error, "指定文件描述不存在！");

                    NotificationManager.Default.SendNotification(catalog,
                        "表单编译失败", "您请求编译的表单 " + temp.Name + "编译失败：\n" +
                        "指定文件描述不存在！\n" +
                        "可能原因为：\n" +
                        "指定文件已在编译前删除\n" +
                        "请求的文件描述ID：" + temp.PhysicalFileId + "\n"
                        );
                }

                this.Components.FileDescriptionProvider.UpdateTag(fileDes.Identity, "Info:正在安装");
                //保存安装好后的模板文件
                using (Stream tempStream = this.Components.PhysicalFileManager.OpenFile(fileDes, FileOpenMode.Read))
                {
                    if (tempStream == null)
                    {
                        NotificationManager.Default.SendNotification(catalog,
                            "表单编译失败", "您请求编译的表单 " + temp.Name + "编译失败：\n" +
                            "打开模板源文件失败！\n" +
                            "可能原因为：\n" +
                            "指定文件已在编译前删除\n" +
                            "请求的文件描述ID：" + temp.PhysicalFileId + "\n"
                            );
                        throw new IOException("打开模板源文件失败！");
                    }

                    if (!Directory.Exists(CompiledFormSavePath))
                    {
                        Directory.CreateDirectory(CompiledFormSavePath);
                    }

                    conventer.ConventWordStreamToCsHtml(tempStream, CompiledFormSavePath + @"\" + temp.Identity + ".cshtml");
                }
                if (!this.Components.FileDescriptionProvider.UpdateTag(fileDes.Identity, "Success:已安装"))
                {
                    this.Components.FormTemplateProvider.UpdateState(temp.Identity, FormTemplateState.Compiled, "编译成功，但未能成功设置源文件备注");
                    NotificationManager.Default.SendNotification(catalog,
                        "表单编译警告", "您请求编译的表单 " + temp.Name + "编译成功，但是出现警告：\n" +
                        "编译成功，但未能成功设置源文件备注！\n" +
                        "可能原因为：\n" +
                        "指定文件已在编译后设置备注前删除\n" +
                        "请求的文件描述ID：" + temp.PhysicalFileId + "\n"
                        );
                }
                else
                {
                    this.Components.FormTemplateProvider.UpdateState(temp.Identity, FormTemplateState.Compiled, "编译成功");
                    NotificationManager.Default.SendNotification(catalog,
                        "表单编译成功", "您请求编译的表单 " + temp.Name + "编译成功！\n" +
                        "编译后的表单名称：" + temp.Name + "\n" +
                        "请求的文件描述ID：" + temp.PhysicalFileId + "\n"
                        );
                }
            }
            catch (Exception ex)
            {
#if DEBUG
                throw ex;
#else
                this.Components.FormTemplateProvider.UpdateState(temp.Identity, FormTemplateState.Error, "编译出错：" + ex.Message);
                if (fileDes != null)
                    this.Components.FileDescriptionProvider.UpdateTag(fileDes.Identity, "Danger:安装失败:" + ex.Message);
                NotificationManager.Default.SendNotification(catalog,
                        "表单编译出错", "您请求编译的表单 " + temp.Name + "编译出现未知错误：\n" +
                        ex.Message + "\n" +
                        "可能原因为：\n" +
                        "文件格式不符合规定或者操作违规\n" +
                        "请求的文件描述ID：" + temp.PhysicalFileId + "\n"
                        );
#endif
            }

        }
        /// <summary>
        /// 开始编译线程
        /// </summary>
        public void Start()
        {
            if (compileTask == null)
            {
                compileTask = new Task(CompileAll);
            }
            switch (compileTask.Status)
            {

                case TaskStatus.Canceled:
                case TaskStatus.Faulted:
                case TaskStatus.RanToCompletion:
                    compileTask.Dispose();
                    compileTask = null;
                    Start();
                    break;
                case TaskStatus.Running:
                    break;
                case TaskStatus.WaitingForActivation:
                case TaskStatus.WaitingForChildrenToComplete:
                    Thread.Sleep(100);
                    Start();
                    break;
                case TaskStatus.Created:
                    compileTask.Start();
                    break;
                case TaskStatus.WaitingToRun:
                    break;
                default:
                    break;
            }
        }
        /// <summary>
        /// 初始化表单模板编译器的静态变量
        /// </summary>
        static FormTemplateCompiler()
        {
            if (HttpContext.Current != null && HttpContext.Current.Server != null)
            {
                CompiledFormSavePath = HttpContext.Current.Server.MapPath("~/") + "WorkFlowForms";
            }
            else
            {
                CompiledFormSavePath = Environment.CurrentDirectory + "/WorkFlowForms";
            }
            Default = new FormTemplateCompiler();
            Default.Start();
        }

    }
}
